package com.young.es.rest.config;

import com.young.es.rest.properties.EsRestClientConfigProperties;
import com.young.es.rest.template.EsRestTemplate;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

@Configuration
@EnableConfigurationProperties(EsRestClientConfigProperties.class)
// 判断当前classpath下是否存在指定类，若存在则将当前的配置装载入spring容器，否则就不进行装配
@ConditionalOnClass(RestHighLevelClient.class)
// 判断配置文件中是否存在指定的配置项，若存在则将当前的配置装载入spring容器，否则就不进行装配
// prefix 表示配置项的公共前缀，可以不写，在name中写全配置项名称可以达到一样的效果
@ConditionalOnProperty(prefix = "elasticsearch",name = {"host","port"})
public class EsRestTemplateAutoConfig {

    @Autowired
    private EsRestClientConfigProperties esRestClientConfigProperties;


    @Bean
    public void esRestTemplate(){
        new EsRestTemplate(restHighLevelClient());
    }

    /*
    * 这里加入@Bean的作用是将restHighLevelClient 这个 bean 交给spring容器管理，
    * 在默认的情况下，spring 容器中的bean是单例的，将该bean 交给spring 容器管理后，
    * 其他被@Bean 注解的方法中如果调用这个方法，那么获取的就是这个单例对象。如上面的esRestTemplate 方法。
    * 另外，由于这个Bean以及被spring 容器管理，所以可以在其他被@Bean注解标注的方法中直接作为参数传入，spring会自动为其注入（依赖传递,依赖注入）
    *
    * 但是这里由于该方法只会被上面的esRestTemplate 方法调用一次，所以也可以不用@Bean注解
    * */
    public RestHighLevelClient restHighLevelClient(){
        HttpHost httpHost =
                new HttpHost(esRestClientConfigProperties.getHost(),
                        esRestClientConfigProperties.getPort());

        RestClientBuilder builder = null;

        if (StringUtils.hasLength(esRestClientConfigProperties.getUsername())
                &&StringUtils.hasLength(esRestClientConfigProperties.getPassword())){
            BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
            basicCredentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(
                    esRestClientConfigProperties.getUsername(), esRestClientConfigProperties.getPassword()
            ));
            builder = RestClient.builder(httpHost).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                @Override
                public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                    return httpAsyncClientBuilder.setDefaultCredentialsProvider(basicCredentialsProvider);
                }
            });

        }else{
            builder = RestClient.builder(httpHost);
        }
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
        return restHighLevelClient;
    }


}
